/*
 * Danne Lundqvist
 * http://www.dotvoid.com
 *
 * Aug 12, 2004, Danne Lundqvist
 * Verson 1.0 - Inital version
 *
 */
var g_draggable = false;


// *******************************************************//
// Item tree object and methods

// Removes a sub item
function ItemRemove(id, itype)
{
	var newItems = new Array();
	var m = 0;
	var remItem;

	for (n = 0; n < this.items.length; n++)
	{
		if (id != this.items[n].id || this.items[n].itype != itype)
			newItems[m++] = this.items[n];
		else
			remItem = this.items[n];
	}

	if (remItem.items.length > 0)
		return false;

	var node = document.getElementById(remItem.fullid);
	node.parentNode.removeChild(node);

	this.items = newItems;
	this.state = 'open';
	this.browser.treeFolder = this;
	this.browser.treeNode   = document.getElementById(this.fullid);
	this.browser.treeNode.className = 'open';
}

// Clear internal list of children
function ItemClear()
{
	this.items = new Array();
}


// Adds a new sub item
function ItemAdd(id, itype, title, icon)
{

	for (n = 0; n < this.items.length; n++)
	{
		if (id == this.items[n].id && this.items[n].itype == itype)
			return false;
	}

	var fullid = this.browser.id + '_' + itype + '_' + id;
	var newItem = new Item(id, this.browser, fullid,
							this, itype, title, icon);
	this.items[this.items.length] = newItem;

	if (itype == 'folder')
	{
		var child = BrowserDrawTreeItem(newItem, this.state, 1);
		var pNode = document.getElementById(this.fullid);
		pNode.parentNode.appendChild(child);
	}
	return newItem;
}

// Class/constructor Item
function Item(id, filebrowser, fullid, parent, itype, title, icon)
{
	// Properties
	this.id     = id;
	this.fullid = fullid;
	this.itype  = itype;
	this.title  = title;
	this.icon   = icon;
	this.state  = 'closed';

	// References
	this.browser = filebrowser;
	this.parent  = parent;
	this.items   = new Array();

	// Methods
	this.add    = ItemAdd;
	this.remove = ItemRemove;
	this.clear  = ItemClear;
}




// *******************************************************//
// Event registration functions

function BrowserOnOpenFolder(func)
{
	this.eventOnOpenFolder = func;
}

function BrowserOnOpenFile(func)
{
	this.eventOnOpenFile = func;
}

function BrowserOnCloseFolder(func)
{
	this.eventOnCloseFolder = func;
}

function BrowserOnCloseFile(func)
{
	this.eventOnCloseFile = func;
}

function BrowserOnDrop(func)
{
	this.eventOnDrop = func;
}


// *******************************************************//
// Drag'n drop functions

function _evtMove(event)
{
  if (!event) event = window.event;
  var x, y = 0;

  if (browser.isIE5up)
    {
      x = event.x;
      y = event.y;
    }
  else
    {
      x = event.pageX;
      y = event.pageY;
    }

  var e = document.getElementById('browser-draggedthumb');
  e.style.left = x + 2 + 'px';
  e.style.top = y + 2 + 'px';
}


function _cancelDrag(event)
{
  var e = document.getElementById('browser-draggedthumb');
  e.style.display = 'none';
  g_draggable = false;
}


function _endDrag(event)
{
  if (!g_draggable)
    return;

  var e = document.getElementById('browser-draggedthumb');
  e.style.display = 'none';

  if (!event) event = window.event;
  evtTarget = (browser.isIE5up) ? event.srcElement : event.target;

  while (evtTarget.nodeName != 'A')
    evtTarget = evtTarget.parentNode;

  var b = evtTarget.item.browser;
  g_draggable = false;

  if (evtTarget.item.itype != 'folder')
    {
      b.dragsrc  = undefined;
      return;
    }

  if (b.dragsrc.id == evtTarget.id)
    {
      b.dragsrc  = undefined;
      return;
    }


	var execMove = true;
	var source = b.dragsrc.item;
	var target = evtTarget.item;
	var parent = source.parent;
  	b.dragsrc  = undefined;

	// Call drop event handler
	if (b.eventOnDrop)
	{
		execMove = b.eventOnDrop(source, target);

		// Execute the move in item tree
		if (execMove)
		{
			newItems = new Array();
			m = 0;
			for (var n = 0; n < parent.items.length; n++)
			{
				if (parent.items[n] != source)
					newItems[m++] = parent.items[n];
			}
			parent.items = newItems;
			target.items[target.items.length] = source;
			source.parent = target;

			BrowserDrawView(b);
			if (source.itype == 'folder')
				BrowserDrawTree(b, true);
		}
	}
}


function _initDrag(event)
{
  if (!event) event = window.event;
  evtTarget = (browser.isIE5up) ? event.srcElement : event.target;

  while (evtTarget.nodeName != 'A')
    evtTarget = evtTarget.parentNode;

  var b = evtTarget.item.browser;
  if (!g_draggable)
    return;

  var e = document.getElementById('browser-draggedthumb');
  e.style.display = 'block';
}


function _canDrag(event)
{
  if (!event) event = window.event;
  evtTarget = (browser.isIE5up) ? event.srcElement : event.target;

  while (evtTarget.nodeName != 'A')
    evtTarget = evtTarget.parentNode;

  var b = evtTarget.item.browser;
  b.dragsrc = evtTarget;
  g_draggable = true;

  var e = document.getElementById('browser-draggedthumb');
  e.innerHTML = evtTarget.innerHTML;
}




// *******************************************************//
// Open/close functions

function _openTreeFolder(evtTarget)
{
	var child = evtTarget.nextSibling;
	var b = evtTarget.item.browser;

	evtTarget.item.state = 'open';

	while(child)
	{
		child.style.display = 'block';
		child = child.nextSibling;
	}

	evtTarget.innerHTML = '<img src="images/filebrowser/treefolder.open.png">&nbsp;' + evtTarget.item.title;

	b.treeFolder = evtTarget.item;
	b.treeNode = evtTarget;

}

function _closeTreeFolder(evtTarget)
{
	var child = evtTarget.nextSibling;
	var b = evtTarget.item.browser;

	evtTarget.item.state = 'closed';

	while(child)
	{
		child.style.display = 'none';
		child = child.nextSibling;
	}
	evtTarget.innerHTML = '<img src="images/filebrowser/treefolder.closed.png">&nbsp;' + evtTarget.item.title;
}

function _evtClickTreeFolder(event)
{
	if (!event) event = window.event;
	evtTarget = (browser.isIE5up) ? event.srcElement : event.target;

	while (evtTarget.nodeName != 'A')
		evtTarget = evtTarget.parentNode;

	var b = evtTarget.item.browser;
	var curTarget = evtTarget.item.browser.treeNode;
	var curFolder = evtTarget.item.browser.treeFolder;
	var hasSubfolders = false;

	if (b.treeNode)
	{
		var children = b.treeFolder.items;
		for (var n = 0; n < children.length; n++)
		{
			if(children[n].itype == 'folder')
			{
				hasSubfolders = true;
				break;
			}
		}
	}

	// Callback for close event
	if (curTarget)
	{
		if (b.eventOnCloseFolder) b.eventOnCloseFolder(curFolder);
	}

	// Callback for open event
	if ((curTarget != evtTarget) || curFolder.state != 'open')
	{
		if (b.eventOnOpenFolder) b.eventOnOpenFolder(evtTarget.item);
	}

	// Set class names
	if (curTarget) curTarget.className = '';
	evtTarget.className = 'open';

	if (curTarget == evtTarget)
	{
		if (curTarget.item.state == 'open')
		{
			evtTarget.className = '';
			_closeTreeFolder(evtTarget);
			b.treeFolder = undefined;
			b.treeNode = undefined;
		}
		else
		{
			_openTreeFolder(evtTarget);
		}
	}
	else if(hasSubfolders)
	{
		_openTreeFolder(evtTarget);
	}
	else
	{
		if (curTarget) _closeTreeFolder(curTarget);
		_openTreeFolder(evtTarget);
	}

	BrowserDrawBar(b);
	BrowserDrawView(b);

	return false;
}



function _evtClickViewItem(event)
{
	if (!event) event = window.event;
	evtTarget = (browser.isIE5up) ? event.srcElement : event.target;

	while (evtTarget.nodeName != 'A')
		evtTarget = evtTarget.parentNode;

	b = evtTarget.item.browser;

	if (evtTarget.item.itype != 'folder')
	{
		if (b.eventOnOpenFile) b.eventOnOpenFile(evtTarget.item);
	}
	if (evtTarget.item.browser.treeFolder)
	{
		folder = b.treeNode.nextSibling;
		while(folder)
		{
			if (folder.firstChild.item.id == evtTarget.item.id)
			{
				if (browser.isIE5up)
				{
					folder.firstChild.fireEvent('onclick');
				}
				else
				{
					oEvent = document.createEvent( "MouseEvents" );
					oEvent.initMouseEvent("click",true,true,window,1,1,1,1,1,
										false,false,false,false,0, folder.firstChild);
					folder.firstChild.dispatchEvent(oEvent);
				}
				break;
			}
			folder = folder.nextSibling;
		}
	}
}



// *******************************************************//
// Manipulation functions

// Create item
// Return value: new item
function BrowserAdd(id, itype, title, icon)
{
	if (itype != 'folder')
	{
		return false;
	}

	for (n = 0; n < this.items.length; n++)
	{
		if (id == this.items[n].id && this.items[n].itype == itype)
			return false;
	}

	var fullid = this.id + '_' + itype + '_' + id;
	var newItem = new Item(id, this, fullid, '', itype, title, icon);
	this.items[this.items.length] = newItem;

	var child = BrowserDrawTreeItem(newItem, 'open', 0)
	this.domtree.appendChild(child);
	return newItem;
}


function BrowserDrawTreeItem(i, pstate, level)
{
	var item = i;
	var state = pstate;
	var lvl = level;
	var substate;

	var div = document.createElement('div');

	if (lvl)
	{
		div.className = 'indent';
	}

	if (state == 'closed')
	{
		div.style.display = 'none';
		substate = 'closed';
	}
	else
	{
		substate = item.state;
	}

	var a = document.createElement('a');
	a.id = item.fullid;
	a.item = item;

	if (browser.isIE5up)
	{
		a.attachEvent("onclick", _evtClickTreeFolder);
		a.attachEvent("onmouseup", _endDrag);
	}
	else
	{
		a.addEventListener("click", _evtClickTreeFolder, false);
		a.addEventListener("mouseup", _endDrag, false);
	}

	if (item == item.browser.treeFolder)
	{
		a.className = 'open';
		item.browser.treeNode = a;
	}

	if (item.state == 'closed')
		a.innerHTML = '<img src="images/filebrowser/treefolder.closed.png">&nbsp;' + item.title;
	else
		a.innerHTML = '<img src="images/filebrowser/treefolder.open.png">&nbsp;' + item.title;

	div.appendChild(a);

	for (var n = 0; n < item.items.length; n++)
	{
		if (item.items[n].itype != 'folder') continue;
		var childdiv = BrowserDrawTreeItem(item.items[n], substate, level + 1);
		div.appendChild(childdiv);
	}

	return div;
}

function BrowserDrawTree(e)
{
	var len = e.items.length;
	if (len < 1) return;

	e.domtree.innerHTML = '';

	for (var n = 0; n < len; n++)
	{
		if (e.items[n].itype != 'folder') continue;
		var child = BrowserDrawTreeItem(e.items[n], 'open', 0);
		e.domtree.appendChild(child);
	}
}

function BrowserDrawBar(e)
{
	var path = '';
	var current = e.treeFolder;

	while (current)
	{
		path = current.title + '/' + path;
		current = current.parent;
	}

	if (path == '') path = '&nbsp;';
	e.dombar.innerHTML = path;
}

function BrowserDrawView(e)
{
	e.domview.innerHTML = '';
	if (!e.treeFolder) return;

	var current  = e.treeFolder;
	var children = current.items;
	var len = children.length;

	for (var n = 0; n < len; n++)
	{
		var a   = document.createElement('a');
		var img = document.createElement('img');
		var br  = document.createElement('br');
		var txt = document.createTextNode(children[n].title);

		if (browser.isIE5up)
		{
			a.attachEvent("onclick", _evtClickViewItem);
			a.attachEvent("onmousedown", _canDrag);
			a.attachEvent("onmousemove", _initDrag);
			a.attachEvent("onmouseup", _endDrag);
		}
		else
		{
			a.addEventListener("click", _evtClickViewItem, false);
			a.addEventListener("mousedown", _canDrag, false);
			a.addEventListener("mousemove", _initDrag, false);
			a.addEventListener("mouseup", _endDrag, false);
		}

		a.href = '#';
		a.className = 'browser-thumb';
		a.id = children[n].fullid;
		a.browsertype = children[n].itype;
		a.item = children[n];

		if (children[n].icon)
		{
			img.src = children[n].icon;
			img.style.border = 'none';
			a.appendChild(img);
		}

		a.appendChild(br);
		a.appendChild(txt);

		e.domview.appendChild(a);
		Drag.init(a);
	}
}

function BrowserRefresh()
{
	BrowserDrawView(this);
}

function BrowserDraw()
{
	BrowserDrawBar(this);
	BrowserDrawView(this);
	BrowserDrawTree(this);
}


// Initalize and create browser
function BrowserInit()
{
	var browser = document.getElementById(this.id);
	this.domtree = document.createElement('div');
	this.domview = document.createElement('div');
	this.dombar = document.createElement('div');

	this.domtree.setAttribute('id', this.id + '_treeview');
	this.domtree.className = 'browser-treeview';

	this.domview.setAttribute('id', this.id + '_fileview');
	this.domview.className = 'browser-fileview';

	this.dombar.setAttribute('id', this.id + '_bar');
	this.dombar.className = 'browser-bar';

	// FIXME: Should be handled by the stylesheet!!!
	var clr = document.createElement('div');
	clr.style.clear = 'both';

	browser.appendChild(this.dombar);
	browser.appendChild(this.domtree);
	browser.appendChild(this.domview);
	browser.appendChild(clr);

	//this.draw();
}


// Create object and defaults
function FileBrowser(id)
{
	this.id        = id;

	this.items      = new Array(); // Item tree
	this.treeFolder = undefined;   // Current tree folder
	this.treeNode   = undefined;
	this.dragsrc    = undefined;

	this.domtree   = undefined;
	this.domview   = undefined;
	this.dombar    = undefined;

	// Event handlers
	this.eventOnOpenFile    = undefined;
	this.eventOnOpenFolder  = undefined;
	this.eventOnCloseFile   = undefined;
	this.eventOnCloseFolder = undefined;
	this.eventOnDrop        = undefined;

	// Event registration functions
	this.onOpenFile    = BrowserOnOpenFile;
	this.onOpenFolder  = BrowserOnOpenFolder;
	this.onCloseFile   = BrowserOnCloseFile;
	this.onCloseFolder = BrowserOnCloseFolder;
	this.onDrop        = BrowserOnDrop;

	// Browser handler functions
	this.init    = BrowserInit;
	this.add     = BrowserAdd;
	this.draw    = BrowserDraw;
	this.refresh = BrowserRefresh;

	if (browser.isIE5up)
	  {
	    document.attachEvent("onmousemove", _evtMove);
	    document.attachEvent("onmouseup", _cancelDrag);
	  }
	else
	  {
	    document.addEventListener("mousemove", _evtMove, false);
	    document.addEventListener("mouseup", _cancelDrag, false);
	  }

	return this;
}
